package com.test.lyt.controller;


import com.amazonaws.ClientConfiguration;
import com.amazonaws.Protocol;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.S3ClientOptions;
import com.amazonaws.services.s3.model.*;
import com.test.lyt.entity.dto.BucketInfoDTO;
import com.test.lyt.entity.dto.MyFileDTO;
import com.test.lyt.uils.PageResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.utils.DateUtils;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;

import static com.test.lyt.constants.MidConstants.*;

@Slf4j
@RestController
@RequestMapping("/bucketService")
public class S3SampleController {

    @Autowired
    private SqlSession sqlSession;

    private final static String END_POINT = "https://obs-helf.cucloud.cn";//请替换成您Bucket所在区域的endpoint

    public AmazonS3 getS3Client() throws IOException {
        BasicAWSCredentials basicAwsCred = new BasicAWSCredentials("6CCB631CFE81471389EA7C7D0EE62A3B3708", "1FE8B67CB73C45B697FCA47EA42DD20D7306"); //请替换成您的AccessKey和SecretKey
        ClientConfiguration clientConfiguration = new ClientConfiguration();
        clientConfiguration.setProtocol(Protocol.HTTPS);
        AmazonS3Client s3 = new AmazonS3Client(basicAwsCred, clientConfiguration);
        S3ClientOptions options = S3ClientOptions.builder().setPathStyleAccess(true).setPayloadSigningEnabled(true).disableChunkedEncoding().build();
        s3.setS3ClientOptions(options);
        s3.setEndpoint(END_POINT);
        return s3;

    }

    @GetMapping("/list")
    public Map<String, List<Map<String, String>>> list() {
        Connection connection = sqlSession.getConnection();
        DatabaseMetaData metaData = null;
        try {
            metaData = connection.getMetaData();
            ResultSet columns = metaData.getColumns(null, null, "test", null);

        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        AmazonS3 s3Client = null;
        try {
            s3Client = this.getS3Client();
        } catch (IOException e) {
            e.printStackTrace();
        }

        S3SampleController sample = new S3SampleController();
        return sample.listBuckets(s3Client);
    }

    public Map<String, List<Map<String, String>>> listBuckets(AmazonS3 ossClient) {
        Map<String, List<Map<String, String>>> map = new HashMap<>();
        List<Map<String, String>> publicList = new ArrayList<>();
        List<Map<String, String>> privateList = new ArrayList<>();

        try {
            ossClient.listBuckets().stream().forEach(bucket -> {
                Map<String, String> bucketMap = new HashMap<>();
                try {
                    AccessControlList acl = ossClient.getBucketAcl(bucket.getName());
                    boolean isPublic = acl.getGrantsAsList().stream().anyMatch(grant ->
                            grant.getGrantee().getIdentifier().equals("http://acs.amazonaws.com/groups/global/AllUsers")
                    );
                    if (isPublic) {
                        bucketMap.put("bucketName", bucket.getName());
                        publicList.add(bucketMap);
                    } else {
                        bucketMap.put("bucketName", bucket.getName());
                        privateList.add(bucketMap);
                    }
                } catch (Exception e) {
                    bucketMap.put("bucketName", bucket.getName());
                    privateList.add(bucketMap);
                    log.error("Failed to check ACL for bucket: " + bucket.getName());
                }
            });
        } catch (Exception e) {
            log.error("list bucket error", e);
        }
        map.put("public", publicList);
        map.put("private", privateList);
        return map;
    }

    @GetMapping("/listObjects")
    public PageResult<MyFileDTO> listObjects() throws IOException {
        AmazonS3 s3 = this.getS3Client();
        //        System.out.println("Listing objects");
//        ObjectListing objectListing = s3.listObjects(new ListObjectsRequest()
//                .withBucketName("dev-private"));
//        for (S3ObjectSummary objectSummary : objectListing.getObjectSummaries()) {
//            System.out.println(" - " + objectSummary.getKey() + "  " +
//                    "(size = " + objectSummary.getSize() + ")");
//
//        }
//        ListObjectsRequest listObjectsRequest = new ListObjectsRequest();
//        listObjectsRequest.setBucketName("test-common-private");
//        listObjectsRequest.setMaxKeys(1000);
//        listObjectsRequest.setMarker("wworkorder/settlement_project_rule_create20220919000015");
//        String nextMarker = s3.listObjects(listObjectsRequest).getNextMarker();


//        List<S3ObjectSummary> objectSummaries = new ArrayList<>();
//        ListObjectsRequest listObjectsRequest = new ListObjectsRequest();
//        listObjectsRequest.setBucketName("test-common-private");

//        // 用于分页的标记
//        String nextMarker = null;
//        do {
//            // 设置请求中的 marker
//            if (StringUtils.isNotEmpty(nextMarker)) {
//                listObjectsRequest.setMarker(nextMarker);
//            }
//            // 获取当前页的对象列表
//            ObjectListing objectListing = s3.listObjects(listObjectsRequest);
//            // 收集当前页的对象摘要信息
//            objectSummaries.addAll(objectListing.getObjectSummaries());
//            // 更新 nextMarker
//            nextMarker = objectListing.getNextMarker();
//        } while (StringUtils.isNotEmpty(nextMarker));
//
//        // 输出结果
//        for (S3ObjectSummary summary : objectSummaries) {
//            System.out.println("Key: " + summary.getKey() + ", Size: " + summary.getSize());
//        }

        // 初始化 ListObjectsV2Request
        ListObjectsV2Request listObjectsV2Request = new ListObjectsV2Request()
                .withBucketName("test-common-public")
                .withPrefix("lyt/")
                .withDelimiter(""); // 使用斜杠作为分隔符

        List<MyFileDTO> list = new ArrayList<>();
        // 用于分页的延续令牌
        String continuationToken = null;

        do {
            // 设置请求中的延续令牌
            if (continuationToken != null) {
                listObjectsV2Request.setContinuationToken(continuationToken);
            }

            // 获取当前页的对象列表
            ListObjectsV2Result result = s3.listObjectsV2(listObjectsV2Request);

            List<String> keyList = new ArrayList<>();
            // 收集当前页的对象摘要信息
            for (S3ObjectSummary summary : result.getObjectSummaries()) {
                String key = summary.getKey();
                LocalDateTime lastModified = summary.getLastModified().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();

                if (checkKey(key, "MALL/")) {
                    MyFileDTO myFileDTO = new MyFileDTO();
                    myFileDTO.setFileId(key);
                    myFileDTO.setLastModifiedTime(lastModified);
                    //判断fileType
                    if (summary.getSize() == 0) {
                        myFileDTO.setFileType(IS_FOLDER);
                    }
                    myFileDTO.setFileType(IS_NOT_FOLDER);
                    myFileDTO.setSize(summary.getSize());
                    list.add(myFileDTO);
                }

            }
            // 更新 continuationToken
            continuationToken = result.getNextContinuationToken();
        } while (continuationToken != null);


        return this.getPaginatedList(list, 1, 5);

    }

    //手动分页
    public PageResult<MyFileDTO> getPaginatedList(List<MyFileDTO> list, int currentPage, int pageSize) {
        int fromIndex = (currentPage - 1) * pageSize;
        int toIndex = Math.min(fromIndex + pageSize, list.size());
        List<MyFileDTO> pageList = list.subList(fromIndex, toIndex);

        return new PageResult<>(pageList, list.size(), currentPage, pageSize);
    }

    private static String getDirectoryFromKey(String key) {
        int lastSlashIndex = key.lastIndexOf('/');
        if (lastSlashIndex == -1) {
            return ""; // 根目录
        }
        return key.substring(0, lastSlashIndex + 1);
    }

    /**
     * 获取同级的目录和文件 都是key
     *
     * @param key
     * @param dir
     * @return
     */
    private boolean checkKey(String key, String dir) {
        if (key.equals(dir)) {
            return false;
        }
        String[] arr = key.split(dir);
        if (arr.length <= 2) {
            String[] arr0 = arr[1].split("/", -1);
            long count = arr[1].chars().filter(o -> o == '/').count();
            if (!arr[1].contains("/")) {
                return true;
            } else if (count == 1 && arr0[arr0.length - 1].equals("")) {
                return true;
            } else {
                return false;
            }
        }
        return false;
    }

    @GetMapping("/getUrl")
    public String getObjectUrl() throws Exception {
        AmazonS3 s3 = this.getS3Client();
        GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest("test-common-public", "lyt/中间件稳定性演练测试用例  V1.1.xlsx");
        //设置链接过期时间
        request.setExpiration(DateUtils.parseDate(LocalDateTime.now().plusDays(7).toString()));
        //生成共享链接
        String s = s3.generatePresignedUrl(request).toString();
        System.out.println("连接是" + s);
        return s;
    }


    /**
     * 下载文件
     *
     * @param
     * @return
     */
    @PostMapping("/download")
    public ResponseEntity<InputStreamResource> download(@RequestBody BucketInfoDTO bucketInfoDTO) throws Exception {
        AmazonS3 s3 = this.getS3Client();
        GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketInfoDTO.getBucketName(), bucketInfoDTO.getFileId());
        PresignedUrlDownloadRequest preRequest = new PresignedUrlDownloadRequest(s3.generatePresignedUrl(request));
        PresignedUrlDownloadResult download = s3.download(preRequest);
        S3ObjectInputStream objectContent = download.getS3Object().getObjectContent();

        // 创建一个InputStreamResource来包装InputStream
        InputStreamResource resource = new InputStreamResource(objectContent);

        // 设置HTTP响应头
        HttpHeaders headers = new HttpHeaders();
        headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + bucketInfoDTO.getFileId());

        return ResponseEntity.ok()
                .headers(headers)
                .contentType(MediaType.APPLICATION_OCTET_STREAM)
                .body(resource);
    }

}